﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using XingFuStudio.Pioneer.Container.Interface;
using System.Reflection;
using XingFuStudio.Pioneer.Container.Interface.Event;
using XingFuStudio.Pioneer.Net;
using XingFuStudio.Pioneer.Entity;
using System.Xml.Linq;

namespace XingFuStudio.Pioneer.Container {
    /// <summary>
    /// 插件管理类
    /// </summary>
    public class PluginManager {

        #region 事件

        /// <summary>
        /// 打印日志事件
        /// </summary>
        public event EventHandler<LogEventArgs> PrintLog = null;
        /// <summary>
        /// 出错事件
        /// </summary>
        public event EventHandler<XingFuStudio.Pioneer.Container.Interface.Event.ErrorEventArgs> Error = null;

        /// <summary>
        /// 执行打印日志事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="isNewLine"></param>
        /// <param name="formate"></param>
        /// <param name="args"></param>
        protected void DoPrintLog(object sender, bool isNewLine, string format, params object[] args) {
            if (this.PrintLog != null) {
                this.PrintLog(sender, new LogEventArgs() { IsNewLing = isNewLine, LogMessage = String.Format(format, args) });
            }
        }

        /// <summary>
        /// 执行出错事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="ex"></param>
        protected void DoError(object sender, Exception ex) {
            if (this.Error != null) {
                this.Error(sender, new XingFuStudio.Pioneer.Container.Interface.Event.ErrorEventArgs() { Exception = ex });
            }
        }

        #endregion

        private string pluginFolder = String.Empty;
        /// <summary>
        /// 单例实例
        /// </summary>
        private static PluginManager instance = null;
        /// <summary>
        /// 
        /// </summary>
        private ApplicationContainer container = null;

        /// <summary>
        /// 创建一个<see cref="插件管理类"/>实例
        /// </summary>
        private PluginManager(string pluginFolder) {
            this.container = new ApplicationContainer();

            this.pluginFolder = pluginFolder;
        }

        /// <summary>
        /// 获取
        /// </summary>
        /// <returns></returns>
        private string[] GetPluginFolders() {
            try {
                //获取存放插件的文件夹路径
                string pluginsDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, this.pluginFolder);
                //获取全部插件的文件夹口路径字符串数组
                string[] pluginDirs = Directory.GetDirectories(pluginsDir);
                //返回插件文件夹（插件名称）
                return pluginDirs;
            } catch {
                return new String[0];
            }
        }

        private void GetPlugins() {
            //获取全部插件名称
            string[] pluginFolders = this.GetPluginFolders();

            //初始化管理配置信息对象
            ConfigManager configManager = new ConfigManager();

            //遍历名称
            foreach (string pluginFolder in pluginFolders) {
                //获取配置文件路径
                string configFilePath = Path.Combine(pluginFolder, "AppConfig.xml");

                //判断是否存在配置文件
                if (File.Exists(configFilePath)) {
                    try {
                        //获取插件配置信息
                        ConfigSection pluginConfig = configManager.GetConfig(configFilePath);

                        //拼接插件程序集所在的路径
                        string assemblyPath = Path.Combine(pluginFolder, pluginConfig.AssemblyName);
                        //获取程序集
                        Assembly assembly = Assembly.LoadFile(assemblyPath);
                        //反射插件接口对象
                        ApplicationBase plugin = (ApplicationBase)assembly.CreateInstance(pluginConfig.TypeName);
                        //判断反射的对象是否为空
                        if (plugin != null) {
                            if (!this.container.Keys.Contains(pluginConfig.PluginName)) {
                                //注册插件
                                this.container.Add(pluginConfig.PluginName, plugin);
                                //打印日志
                                this.DoPrintLog(null, true, "加载插件[{0}]...OK! ", pluginConfig.PluginName);
                            }
                        } else {
                            //写系统日志
                            DoError(null, new Exception(String.Format("加载插件 {0} 出错：{1} {2}", pluginFolder, "反射失败", pluginConfig.TypeName)));
                        }
                    } catch (Exception ex) {
                        //写系统日志
                        DoError(null, new Exception(String.Format("加载插件 {0} 出错：{1}", pluginFolder, ex.Message), ex));
                    }
                }
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Initialize() {
            //获取插件
            this.GetPlugins();

            foreach (string key in this.container.Keys) {
                //获取插件对象
                ApplicationBase plugin = this.container[key];
                //注册事件
                plugin.PrintLog += new EventHandler<LogEventArgs>(plugin_PrintLog);
                plugin.Error += new EventHandler<XingFuStudio.Pioneer.Container.Interface.Event.ErrorEventArgs>(plugin_Error);
                plugin.LoginFailed += new EventHandler<LoginFailedEventArgs>(plugin_LoginFailed);
                plugin.Persistence += new EventHandler<PersistenceEventArgs>(plugin_Persistence);

                //初始化插件
                plugin.Initialize(key);
            }

            //加载序列化的数据对象
            foreach (string key in this.container.Keys) {
                //获取序列化数据
                XElement data = PresistenceEngine.GetInstance().Load(key);

                //判断数据是否为空
                if (data != null) {
                    //获得当前应用对象
                    ApplicationBase app = this.container[key];
                    //为当前应用赋值序列化数据
                    app.SetPersistenceXML(data);
                }
            }
        }

        /// <summary>
        /// 运行
        /// </summary>
        /// <param name="httpManager"></param>
        /// <param name="account"></param>
        public void Run(List<AccountInfo> accounts) {
            foreach (string key in this.container.Keys) {
                //获取插件对象
                ApplicationBase plugin = this.container[key];
                //运行
                plugin.Run(accounts);
            }
        }

        /// <summary>
        /// 暂停
        /// </summary>
        public void Pause() {
            foreach (string key in this.container.Keys) {
                //获取插件对象
                ApplicationBase plugin = this.container[key];
                //暂停
                plugin.Pause();
            }
        }

        /// <summary>
        /// 停止
        /// </summary>
        public void Stop() {
            foreach (string key in this.container.Keys) {
                //获取插件对象
                ApplicationBase plugin = this.container[key];
                //停止
                plugin.Stop();
            }
        }

        /// <summary>
        /// 插件出错事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void plugin_Error(object sender, XingFuStudio.Pioneer.Container.Interface.Event.ErrorEventArgs e) {
            this.DoError(sender, e.Exception);
        }

        /// <summary>
        /// 插件打印日志
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void plugin_PrintLog(object sender, LogEventArgs e) {
            this.DoPrintLog(sender, e.IsNewLing, e.LogMessage);
        }

        /// <summary>
        /// 应用登录失败事件方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void plugin_LoginFailed(object sender, LoginFailedEventArgs e) {
            //throw new NotImplementedException();
        }

        /// <summary>
        /// 应用持久化事件方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void plugin_Persistence(object sender, PersistenceEventArgs e) {
            ApplicationBase app = (ApplicationBase)sender;

            if (app != null) {
                PresistenceEngine.GetInstance().Save(app.PluginName, e.PersistenceData);
            }
        }

        /// <summary>
        /// 获取插件名称
        /// </summary>
        public List<string> pluginNames {
            get {
                return this.container.Keys.ToList();
            }
        }
        
        /// <summary>
        /// 创建一个单例对象
        /// </summary>
        /// <returns></returns>
        public static PluginManager GetInstance(string pluginFolder) {
            if (instance == null) {
                instance = new PluginManager(pluginFolder);
            }

            return instance;
        }
    }
}
